From 688e95c3b338a33c73ae8493c823a98c3ebe7e86 Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Mon, 14 May 2012 16:17:46 +0100 Subject: [PATCH] libxl: prevent xl from doing operations on domains if xend is running Prevent xl from doing any operation if xend daemon is running. That prevents bugs that happened when xl and xend raced to close a domain. Signed-off-by: Roger Pau Monne Acked-by: Ian Jackson Committed-by: Ian Jackson --- docs/man/xl.pod.1 | 6 ++ tools/libxl/xl.c | 22 ++++++- tools/libxl/xl.h | 1 + tools/libxl/xl_cmdimpl.c | 5 +- tools/libxl/xl_cmdtable.c | 130 +++++++++++++++++++------------------- 5 files changed, 96 insertions(+), 68 deletions(-) diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1 index 283c9ed2ac..b192efadf6 100644 --- a/docs/man/xl.pod.1 +++ b/docs/man/xl.pod.1 @@ -75,6 +75,12 @@ Verbose. Dry run: do not actually execute the command. +=item B<-f> + +Force execution: xl will refuse to run some commands if it detects that xend is +also running, this option will force the execution of those commands, even +though it is unsafe. + =back =head1 DOMAIN SUBCOMMANDS diff --git a/tools/libxl/xl.c b/tools/libxl/xl.c index d4db1f8b8b..750a61c54c 100644 --- a/tools/libxl/xl.c +++ b/tools/libxl/xl.c @@ -32,8 +32,11 @@ #include "libxlutil.h" #include "xl.h" +#define XEND_LOCK { "/var/lock/subsys/xend", "/var/lock/xend" } + xentoollog_logger_stdiostream *logger; int dryrun_only; +int force_execution; int autoballoon = 1; char *lockfile; char *default_vifscript = NULL; @@ -126,8 +129,9 @@ int main(int argc, char **argv) char *config_file; void *config_data = 0; int config_len = 0; + const char *locks[] = XEND_LOCK; - while ((opt = getopt(argc, argv, "+vN")) >= 0) { + while ((opt = getopt(argc, argv, "+vfN")) >= 0) { switch (opt) { case 'v': if (minmsglevel > 0) minmsglevel--; @@ -135,6 +139,9 @@ int main(int argc, char **argv) case 'N': dryrun_only = 1; break; + case 'f': + force_execution = 1; + break; default: fprintf(stderr, "unknown global option\n"); exit(2); @@ -185,6 +192,19 @@ int main(int argc, char **argv) ret = 1; goto xit; } + if (cspec->modifies && !dryrun_only) { + for (int i = 0; i < sizeof(locks)/sizeof(locks[0]); i++) { + if (!access(locks[i], F_OK) && !force_execution) { + fprintf(stderr, +"xend is running, which prevents xl from working correctly.\n" +"If you still want to force the execution of xl please use the -f\n" +"option.\n" + ); + ret = 1; + goto xit; + } + } + } ret = cspec->cmd_impl(argc, argv); } else if (!strcmp(cmd, "help")) { help(argv[1]); diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h index 2b6714af36..5d0d50440f 100644 --- a/tools/libxl/xl.h +++ b/tools/libxl/xl.h @@ -21,6 +21,7 @@ struct cmd_spec { char *cmd_name; int (*cmd_impl)(int argc, char **argv); int can_dryrun; + int modifies; char *cmd_desc; char *cmd_usage; char *cmd_option; diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index efaf3de047..5fc5cde2d2 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -1937,7 +1937,7 @@ void help(const char *command) struct cmd_spec *cmd; if (!command || !strcmp(command, "help")) { - printf("Usage xl [-vN] [args]\n\n"); + printf("Usage xl [-vfN] [args]\n\n"); printf("xl full list of subcommands:\n\n"); for (i = 0; i < cmdtable_len; i++) { printf(" %-19s ", cmd_table[i].cmd_name); @@ -1948,7 +1948,8 @@ void help(const char *command) } else { cmd = cmdtable_lookup(command); if (cmd) { - printf("Usage: xl [-v%s] %s %s\n\n%s.\n\n", + printf("Usage: xl [-v%s%s] %s %s\n\n%s.\n\n", + cmd->modifies ? "f" : "", cmd->can_dryrun ? "N" : "", cmd->cmd_name, cmd->cmd_usage, diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c index 2796460fea..9d33707544 100644 --- a/tools/libxl/xl_cmdtable.c +++ b/tools/libxl/xl_cmdtable.c @@ -19,7 +19,7 @@ struct cmd_spec cmd_table[] = { { "create", - &main_create, 1, + &main_create, 1, 1, "Create a domain from config file ", " [options] [vars]", "-h Print this help.\n" @@ -33,7 +33,7 @@ struct cmd_spec cmd_table[] = { "-e Do not wait in the background for the death of the domain." }, { "config-update", - &main_config_update, 1, + &main_config_update, 1, 1, "Update a running domain's saved configuration, used when rebuilding " "the domain after reboot", " [options] [vars]", @@ -42,7 +42,7 @@ struct cmd_spec cmd_table[] = { "-d Enable debug messages.\n" }, { "list", - &main_list, 0, + &main_list, 0, 0, "List information about all/some domains", "[options] [Domain]\n", "-l, --long Output all VM details\n" @@ -50,12 +50,12 @@ struct cmd_spec cmd_table[] = { "-Z, --context Prints out security context" }, { "destroy", - &main_destroy, 0, + &main_destroy, 0, 1, "Terminate a domain immediately", "", }, { "shutdown", - &main_shutdown, 0, + &main_shutdown, 0, 1, "Issue a shutdown signal to a domain", "[options] ", "-h Print this help.\n" @@ -64,7 +64,7 @@ struct cmd_spec cmd_table[] = { "-w Wait for guest to shutdown.\n" }, { "reboot", - &main_reboot, 0, + &main_reboot, 0, 1, "Issue a reboot signal to a domain", "[options] ", "-h Print this help.\n" @@ -72,44 +72,44 @@ struct cmd_spec cmd_table[] = { " no PV drivers.\n" }, { "pci-attach", - &main_pciattach, 0, + &main_pciattach, 0, 1, "Insert a new pass-through pci device", " [Virtual Slot]", }, { "pci-detach", - &main_pcidetach, 0, + &main_pcidetach, 0, 1, "Remove a domain's pass-through pci device", " ", }, { "pci-list", - &main_pcilist, 0, + &main_pcilist, 0, 0, "List pass-through pci devices for a domain", "", }, { "pci-list-assignable-devices", - &main_pcilist_assignable, 0, + &main_pcilist_assignable, 0, 0, "List all the assignable pci devices", "", }, { "pause", - &main_pause, 0, + &main_pause, 0, 1, "Pause execution of a domain", "", }, { "unpause", - &main_unpause, 0, + &main_unpause, 0, 1, "Unpause a paused domain", "", }, { "console", - &main_console, 0, + &main_console, 0, 0, "Attach to domain's console", "[options] \n" "-t console type, pv or serial\n" "-n console number" }, { "vncviewer", - &main_vncviewer, 0, + &main_vncviewer, 0, 0, "Attach to domain's VNC server.", "[options] \n" "--autopass Pass VNC password to viewer via stdin and\n" @@ -117,14 +117,14 @@ struct cmd_spec cmd_table[] = { "--vncviewer-autopass (consistency alias for --autopass)" }, { "save", - &main_save, 0, + &main_save, 0, 1, "Save a domain state to restore later", "[options] []", "-h Print this help.\n" "-c Leave domain running after creating the snapshot." }, { "migrate", - &main_migrate, 0, + &main_migrate, 0, 1, "Save a domain state to restore later", "[options] ", "-h Print this help.\n" @@ -136,12 +136,12 @@ struct cmd_spec cmd_table[] = { " of the domain." }, { "dump-core", - &main_dump_core, 0, + &main_dump_core, 0, 1, "Core dump a domain", " " }, { "restore", - &main_restore, 0, + &main_restore, 0, 1, "Restore a domain from a saved state", "[options] [] ", "-h Print this help.\n" @@ -150,68 +150,68 @@ struct cmd_spec cmd_table[] = { "-d Enable debug messages." }, { "migrate-receive", - &main_migrate_receive, 0, + &main_migrate_receive, 0, 1, "Restore a domain from a saved state", "- for internal use only", }, { "cd-insert", - &main_cd_insert, 0, + &main_cd_insert, 0, 1, "Insert a cdrom into a guest's cd drive", " ", }, { "cd-eject", - &main_cd_eject, 0, + &main_cd_eject, 0, 1, "Eject a cdrom from a guest's cd drive", " ", }, { "mem-max", - &main_memmax, 0, + &main_memmax, 0, 1, "Set the maximum amount reservation for a domain", " ", }, { "mem-set", - &main_memset, 0, + &main_memset, 0, 1, "Set the current memory usage for a domain", " ", }, { "button-press", - &main_button_press, 0, + &main_button_press, 0, 1, "Indicate an ACPI button press to the domain", "